package com.anmi.alfred.service.concreteservice;

import com.anmi.alfred.entity.TransferCaseOperationResult;
import com.anmi.alfred.response.base.ResponseEntity;
import com.anmi.alfred.response.concrete.CaseOperationResponse;
import com.anmi.alfred.service.baseservice.SearchService;
import com.anmi.alfred.util.CopyUtil;
import com.anmi.alfred.util.DateUtil;
import com.anmi.domain.dto.CaseOperationParamDto;
import com.anmi.domain.dto.CaseOperationResultDto;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.sort.FieldSortBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
@Slf4j
public class CaseOperationSearchService extends SearchService {

  /**
   * 带条件查询
   *
   * @param indexName 索引名称
   * @param paramDto 查询参数
   */
  public ResponseEntity<List<CaseOperationResultDto>> caseOperationTermQuery(
      String indexName, CaseOperationParamDto paramDto) {
    List<CaseOperationResultDto> target;
    if (paramDto == null) {
      return ResponseEntity.error(10001, "参数不能为空");
    }
    try {
      target = getCaseOperationResultDtoData(indexName, paramDto);
      return ResponseEntity.success(0, "查询成功", target);
    } catch (RuntimeException e) {
      log.error("查询失败,{}", e.getMessage());
      return ResponseEntity.error(500, "查询失败");
    }
  }

  /**
   * 这里的方法是将Elasticsearch查询的total也一起返回， 与 {@link #caseOperationTermQuery(String,
   * CaseOperationParamDto)} 方法不同的就是返回了查询的总数，如果不使用，可以考虑删除
   *
   * @param indexName
   * @param paramDto
   * @return
   */
  public ResponseEntity<CaseOperationResponse> caseOperationDataAndTotalQuery(
      String indexName, CaseOperationParamDto paramDto) {
    List<CaseOperationResultDto> target;
    if (paramDto == null) {
      return ResponseEntity.error(10001, "参数不能为空");
    }
    try {
      int from = (paramDto.getPage() - 1) * paramDto.getLimit();
      int size = paramDto.getLimit();
      SearchRequest searchRequest = new SearchRequest(indexName);
      searchRequest.source(assembleCaseOperationSearchSourceBuilder(paramDto, from, size));
      SearchResponse response = search(searchRequest);
      List<String> list = resolveSearchResponse(response);
      List<TransferCaseOperationResult> sourceList =
          convert(list, TransferCaseOperationResult.class);
      target = CopyUtil.copyList(sourceList, CaseOperationResultDto.class);
      CaseOperationResponse caseOperationResponse = new CaseOperationResponse();
      caseOperationResponse.setList(target);
      caseOperationResponse.setTotalNum(resolveSearchHItsTotalNum(response));
      return ResponseEntity.success(0, "查询成功", caseOperationResponse);
    } catch (RuntimeException e) {
      log.error("查询失败,{}", e.getMessage());
      return ResponseEntity.error(500, "查询失败");
    }
  }

  private List<CaseOperationResultDto> getCaseOperationResultDtoData(
      String indexName, CaseOperationParamDto paramDto) {
    List<CaseOperationResultDto> target;
    int from = (paramDto.getPage() - 1) * paramDto.getLimit();
    int size = paramDto.getLimit();
    SearchRequest searchRequest = new SearchRequest(indexName);
    searchRequest.source(assembleCaseOperationSearchSourceBuilder(paramDto, from, size));
    SearchResponse response = search(searchRequest);
    List<String> list = resolveSearchResponse(response);
    List<TransferCaseOperationResult> sourceList = convert(list, TransferCaseOperationResult.class);
    target = CopyUtil.copyList(sourceList, CaseOperationResultDto.class);
    return target;
  }

  /**
   * 组装查询参数
   *
   * @param dto 查询参数
   * @return
   */
  private SearchSourceBuilder assembleCaseOperationSearchSourceBuilder(
      CaseOperationParamDto dto, int from, int size) {
    BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();

    // 总公司ID
    if (dto.getOrgId() != null) {
      // 正确
      boolQueryBuilder.must(QueryBuilders.termQuery("orgId", dto.getOrgId()));
    }

    // 分公司ID
    if (dto.getDepId() != null) {
      // 正确
      boolQueryBuilder.must(QueryBuilders.termQuery("depId", dto.getDepId()));
    }

    // 催员多选 ES 设置为keyword类型，不分词
    if (StringUtils.isNotBlank(dto.getUserIds())) {
      // 正确
      String[] userIds = dto.getUserIds().split(",");
      boolQueryBuilder.must(QueryBuilders.termsQuery("createBy", userIds));
    }
    // 开始时间
    if (dto.getStartTime() != null) {
      // 正确
      boolQueryBuilder.must(
          QueryBuilders.rangeQuery("createTime")
              .format("yyyy-MM-dd HH:mm:ss")
              .from(DateUtil.DateToStr(dto.getStartTime(), DateUtil.yyyyMMddHHmmss)));
    }
    // 结束时间
    if (dto.getEndTime() != null) {
      // 正确
      boolQueryBuilder.must(
          QueryBuilders.rangeQuery("createTime")
              .format("yyyy-MM-dd HH:mm:ss")
              .to(DateUtil.DateToStr(dto.getEndTime(), DateUtil.yyyyMMddHHmmss)));
    }

    // 催收进程 设置keyword，不分词
    if (StringUtils.isNotBlank(dto.getOperationStates())) {
      // 正确
      String[] operationStates = dto.getOperationStates().split(",");
      boolQueryBuilder.must(QueryBuilders.termsQuery("operationState", operationStates));
    }

    // 催收结果
    if (StringUtils.isNotBlank(dto.getActionTypes())) {
      // 正确
      String[] actionTypes = dto.getActionTypes().split(",");
      boolQueryBuilder.must(QueryBuilders.termsQuery("actionType", actionTypes));
    }

    // 委案公司编号 , 多选情况
    if (StringUtils.isNotBlank(dto.getOrgDeltIds())) {
      // 正确
      String[] orgDeltIds = dto.getOrgDeltIds().split(",");
      boolQueryBuilder.must(QueryBuilders.termsQuery("orgDeltId", orgDeltIds));
    }

    // 委案产品
    if (StringUtils.isNotBlank(dto.getProductIds())) {
      // 正确
      String[] productIds = dto.getProductIds().split(",");
      boolQueryBuilder.must(QueryBuilders.termsQuery("productId", productIds));
    }

    // 现在委案方批次号为模糊匹配，可能需要修改为精确匹配
    if (StringUtils.isNotBlank(dto.getOutBatchIds())) {
      String[] outBatchIds = dto.getOutBatchIds().split(",");
      boolQueryBuilder.must(QueryBuilders.termsQuery("outBatchId", outBatchIds));
    }

    // 委案编号
    if (dto.getOutSerialNos() != null && dto.getOutSerialNos().size() > 0) {
      if (dto.getOutSerialNos().size() == 1) {
        // 一个，前缀模糊搜索
        // 这里的ES的本来的查询字段应该是outSerialNo，由于安米对outSerialNo还需要做处理，所以在不改动安米的基础上，
        // 使用ES pipeline在文档索引之前添加了该查询字段，仅作为查询使用
        boolQueryBuilder.must(
            QueryBuilders.wildcardQuery(
                "outSerialNoSearch.keyword", dto.getOutSerialNos().get(0) + "*"));
      } else {
        boolQueryBuilder.must(
            QueryBuilders.termsQuery("outSerialNoSearch.keyword", dto.getOutSerialNos()));
      }
    }

    // 债务人 如果参数为一个，那可以模糊匹配，如果为多个参数，那就是精确匹配:)
    if (dto.getNames() != null && dto.getNames().size() > 0) {
      if (dto.getNames().size() == 1) {
        boolQueryBuilder.must(
            QueryBuilders.wildcardQuery("name.keyword", dto.getNames().get(0) + "*"));
      } else {
        boolQueryBuilder.must(QueryBuilders.termsQuery("name.keyword", dto.getNames()));
      }
    }

    // 案件联系人手机号 如果参数为一个，那可以模糊匹配，如果为多个参数，那就是精确匹配:)
    if (dto.getConMobiles() != null && dto.getConMobiles().size() > 0) {
      if (dto.getConMobiles().size() == 1) {
        boolQueryBuilder.must(
            QueryBuilders.wildcardQuery("conMobile.keyword", dto.getConMobiles().get(0) + "*"));
      } else {
        boolQueryBuilder.must(QueryBuilders.termsQuery("conMobile.keyword", dto.getConMobiles()));
      }
    }

    // 债务人手机号 如果参数为一个，那可以模糊匹配，如果为多个参数，那就是精确匹配:)
    if (dto.getOwnMobiles() != null && dto.getOwnMobiles().size() > 0) {
      if (dto.getOwnMobiles().size() == 1) {
        boolQueryBuilder.must(
            QueryBuilders.wildcardQuery("ownMobile.keyword", dto.getOwnMobiles().get(0) + "*"));
      } else {
        boolQueryBuilder.must(QueryBuilders.termsQuery("ownMobile.keyword", dto.getOwnMobiles()));
      }
    }

    // 案件ID
    if (dto.getCaseId() != null) {
      boolQueryBuilder.must(QueryBuilders.termQuery("caseId", dto.getCaseId()));
    }
    return new SearchSourceBuilder()
        .query(boolQueryBuilder)
        .from(from)
        .size(size)
        .sort(new FieldSortBuilder("createTime").order(SortOrder.DESC));
  }
}
